#include <cstring>
#include <cmath>   
#include <iostream>  //预处理器指令 a PREPROCESSOR directive
#include <vector>
#include <array>

using namespace std; //使定义可见   make definitions visible

class StringBad
{
private:
  char *str;              // pointer to string
  int len;                // length of string
  static int num_strings; // number of objects 记录所创建的对象数目
public:
  StringBad(const char *s); // constructor
  StringBad();              // default constructor
  ~StringBad();             // destructor

  void change_str(const char * s);

  StringBad(const StringBad& st); //复制构造函数 (深度复制)
  // StringBad& operator=(const StringBad& st); //赋值运算符 (深度复制)

  // friend function
  friend std::ostream &operator<<(std::ostream &os,
                                  const StringBad &st);
};

void callme2(StringBad sb);

int main(){

  StringBad st1 = StringBad("abc");
  StringBad st2 = StringBad("123");

  StringBad st3;
  st3 = st2;

  //st3.change_str("789");

  // callme2(st1);
  // callme2(st1);
}

//将headline2作为函数参数来传递从而导致析构函数被调用。
void callme2(StringBad sb)
{ 
  //String passed by value
  cout << "通过值传递的字符串: ";
  cout << "    \"" << sb << "\"\n";
}


// initializing static class member
int StringBad::num_strings = 0;


// construct StringBad from C string
StringBad::StringBad(const char *s)
{
  len = std::strlen(s);    // set size
  str = new char[len + 1]; // allot storage 分配存储
  std::strcpy(str, s);     // initialize pointer 初始化指针 
  num_strings++;           // set object count 

  // For Your Information 供参考
  cout << num_strings << ": \"" << str << "\" object created\n"; 
}

void StringBad::change_str(const char * s){
    // For Your Information 供参考
  cout << str << "\" object changed " << s << endl; 

  delete[] str;//free old string
  len = std::strlen(s);    // set size
  str = new char[len+1];//get space for new string
  std::strcpy(str, s); 
}

//析构函数
StringBad::~StringBad() // necessary destructor
{
  cout << "\"" << str << "\" object deleted, "; // FYI
  --num_strings;                                // required
  cout << num_strings << " left\n";             // FYI
  delete[] str;                                 // required 这里注释防止程序报错,因为StringBad类是个不完善
                                                // 增加 赋值运算符 (深度复制) 复制构造函数 (深度复制) 后就不需要注释了
}

//友元函数 重载 << , 使cout可以输出StringBad对象
std::ostream &operator<<(std::ostream &os, const StringBad &st)
{
  os << st.str;
  return os;
}

// //赋值运算符 (深度复制)
// StringBad& StringBad::operator=(const StringBad& st){
//   cout << st.str << " call = 运算符" << endl;
//   //函数应当避免将对象赋给自身
//   if(this == &st)//object assigned to itself 
//     return *this;//all done

//   //由于目标对象可能引用了以前分配的数据,释放这些数据
//   delete[] str;//free old string
//   len = st.len;
//   str = new char[len+1];//get space for new string
//   std::strcpy(str,st.str);//copythestring
//   return *this;//return reference to invoking object 返回调用对象的引用 
// }

StringBad::StringBad() // default constructor
{
  len = 4;
  str = new char[4];
  std::strcpy(str, "C++"); // default string
  num_strings++;
 
  // FYI
  cout << num_strings << ": \"" << str << "\" default object created\n";
}


//复制构造函数 (深度复制)
//每当程序生成了对象副本时，编译器都将使用复制构造函数。
StringBad::StringBad(const StringBad& st){
  num_strings++;//handle static member update
  len = st.len;//same length
  str=new char[len+1];//allot space
  std::strcpy(str,st.str);//copy string to new location
  cout<<num_strings<<": \""<<str  <<"\" object copy created \n";//For Your Information
}